package commons.io.in;

import algo_annotations.params.objects.ContrainteGeomSegment;
import algo_lignes_sites.params.objects.contraintesgeom.ContrainteGeomLine;
import commons.params_appli.ParamsAppli;
import commons.data.Attributes;
import commons.data.EchelleGeneralization;
import commons.data.Zones;
import commons.drawing.SegmentDrawable;
import commons.utils.primitive_geom.Point_d;
import java.awt.Color;
import java.util.ArrayList;

public class Segment_in extends SegmentDrawable implements IObjetGeo_in {

	// Infos utilisées par les algo LigneSite et Annotation
	public Attributes attributes_in;
	public Zones zones;
	public EchelleGeneralization echelleGeneralization;
	// public Color color; deja dans super ...

	// Infos propres à l'algo Ligne-Site
	public ContrainteGeomLine contrainteGeomLine;

	// Infos propres à l'algo Anno
	public ContrainteGeomSegment contrainteGeomSegment;

	
	public boolean hasDissymetrie() {return contrainteGeomLine.hasDissymetrie();}
	
	public Attributes attributes_fusion;

	public Attributes getAttributes_fusion() {return attributes_fusion;}
	@Override
	public Attributes getAttributes_in() {return attributes_in;}

	public Segment_in(Point_d pt1, Point_d pt2, Attributes attributes_in) {
		super (pt1, pt2, ParamsAppli.getParam_c("AutoGene.COULEUR_SEGMENT"), -1, (float)ParamsAppli.getParam_d("AutoGene.EPAISSEUR_SEGMENT"));
		//super (pt1, pt2, Color.PINK, -1, 1);
		
		this.attributes_in = attributes_in;
		
		this.zones = new Zones();
		this.contrainteGeomLine = null;
		this.contrainteGeomSegment = null;
		this.echelleGeneralization = null;
	}

	public Segment_in(Segment_in seg) {
		this (seg.pt1, seg.pt2, seg.attributes_in);
		this.contrainteGeomLine = seg.contrainteGeomLine;
		this.contrainteGeomSegment = seg.contrainteGeomSegment;
		this.echelleGeneralization = seg.echelleGeneralization;
		this.zones = seg.zones;
		this.color = seg.color;
	}

	
	@Override
	public void clear() {
		attributes_in = null;
		attributes_fusion = null;
		zones = null;
	}
	
	@Override
	public Zones getZones() {return zones;}
	
	public void invert() {
		Point_d temp;
		temp = pt1;
		pt1 = pt2;
		pt2 = temp;
	}

	//**************************************************************************
	// variables et méthodes pour traiter de façon optimisée le calcul des intersections

	// Liste des points d'intersection détectés pendant le parcours de tous les
	//  segments 2 à 2 (le découpage se fera à la fin de ce parcours)
	private ArrayList<Point_d> vPtIntersect;
	public int getNbPtIntersection () {if (vPtIntersect==null) return 0; else return vPtIntersect.size();}
	public ArrayList<Point_d> getVPointIntersect() {return vPtIntersect;}

	public void addPtIntersection (Point_d ptI) {
		if (vPtIntersect==null) vPtIntersect = new ArrayList<Point_d>(3);
		vPtIntersect.add(ptI);
	}

	// Renvoit l'ensemble des segments résultant du split de this selon les points
	//  d'intersection pré-calculés et stockés dans 'vPtIntersect'
	// Fonctionne même si les points sont en doublons et pas dans l'ordre
	public ArrayList<Segment_in> decoupe() {
		ArrayList<Segment_in> vSegDecoupe = new ArrayList<Segment_in>(3);
		
		// On part d'un premier segment, égal au segment total this
		vSegDecoupe.add(new Segment_in(pt1, pt2, attributes_in));
		
		// puis on cherche dans ce vecteur, à chaque itération successive
		// à découper l'un des segments
		// dans le cas où il n'y a pas de doublons dans les point d'intersection
		// on doit forcément trouver 1 unique segment à découper
		// en effet, dans la construction des points d'intersection, on s'est
		// arrangé pour ne pas mettre ceux correspondant à l'une des extrémités du segment
		for (int i = 0; i < vPtIntersect.size(); i++) {
			Point_d ptI = vPtIntersect.get(i);
			for (int j = 0; j < vSegDecoupe.size(); j++) {
				Segment_in seg = vSegDecoupe.get(j);
				// pt se trouve-t-il sur ce segment ?
				// on teste sur les x et y , au cas ou le segment est horizontal ou vertical
				if ((ptI.x > Math.min(seg.pt1.x, seg.pt2.x) && ptI.x < Math.max(seg.pt1.x, seg.pt2.x)) ||
					(ptI.y > Math.min(seg.pt1.y, seg.pt2.y) && ptI.y < Math.max(seg.pt1.y, seg.pt2.y))) {
					// on a trouve notre segment à découper : on en crée 2
					// en fait, on raccourci celui déjà dans le vecteur et on en
					// ajoute un nouveau à la fin du vecteur
					vSegDecoupe.add (new Segment_in(ptI, seg.pt2, attributes_in));
					seg.pt2 = ptI;
					
					//pas la peine de chercher d'autres segments à découper ...
					// on passe au point d'intersection suivant
					break;
				}
			}
		}
		return vSegDecoupe;
	}


	// La copie ne porte que sur les coordonnées : celles de la copie deviennent indépendante de l'original
	@Override
	public IObjetGeo_in makeCopy() {
		Segment_in seg = new Segment_in(this);
		seg.zones = zones;
		// Le seul moment ou cette fonction est utilisée, les autres variables ne sont meme pas utilisée
		assert(echelleGeneralization==null && contrainteGeomLine==null && contrainteGeomSegment==null);
		return seg;
	}

	@Override
	public String getInfoDetaillee() {
		return super.toString() + "\n" + attributes_in.toString();
	}

}
